<?php

class FightModel extends Model {
	//悬赏挑战，去战斗
    public static function offerfight($uid = 0, $tuid = 0, $auid = 0)
	{
		$uid = intval($uid);
		$tuid = intval($tuid);
		$auid = intval($auid);
		if(!$uid || !$tuid || !$auid) return array('ecode' => ERR302);

		$offer = daocall("offer", "getoffer", array($uid, $tuid));
		if(!$offer || $offer["auid"] != $auid || !$offer["actm"] || (time() - $offer["actm"]) > 86400) return array("ecode" => ERR802);

		$uext = daocall("user", "getuserext", array($uid));
        if (!$uext || !is_array($uext)) return array('ecode' => ERR402);
		$uext["lv"] = modcall("user", "xp2lv", array($uext["xp"]));
		$ulv = $uext["lv"]; 

		$tuext = daocall("user", "getuserext", array($tuid));
        if (!$tuext || !is_array($tuext)) return array('ecode' => ERR402);
		$tuext["lv"] = modcall("user", "xp2lv", array($tuext["xp"]));
		$tulv = $tuext["lv"];

		$auext = daocall("user", "getuserext", array($auid));
        if (!$auext || !is_array($auext)) return array('ecode' => ERR402);
		$auext["lv"] = modcall("user", "xp2lv", array($auext["xp"]));
		$aulv = $auext["lv"];

		$ret = self::fight($auid, $tuid);
		if($ret["ecode"]) return $ret;




		$hgs = daocall("herogroup", "getherogroups", array($uid));
		$thgs = daocall("herogroup", "getherogroups", array($tuid));
        if (!$hgs || !$thgs) return array('ecode' => ERR508);
		$cherogroup = $tcherogroup = array();
		foreach($hgs as $gid => $grow)
		{
			if($grow["stat"])
			{
				$cherogroup = $grow;
				break;
			}
		}
		foreach($thgs as $gid => $grow)
		{
			if($grow["stat"])
			{
				$tcherogroup = $grow;
				break;
			}
		}
		unset($hgs, $thgs);
		if(!$cherogroup || !$tcherogroup) return array('ecode' => ERR508);

		$heros = daocall("hero", "getheros", array($uid));
		$theros = daocall("hero", "getheros", array($tuid));
		if(!$heros || !$theros) return array('ecode' => ERR505);

		$heroconf = load_conf("pub:hero");
		if(!$heroconf || !$heroconf["hero"]) return array('ecode' => ERR505);
		$heroconf = $heroconf["hero"];


		return array("ecode" => SUCCESS, "ret" => array("win" => $win, "log" => $attlog));

		/*
		总英雄经验获得公式
		胜利
		总英雄经验=100*（1+（防守方用户等级-1）*0.2）
		失败
		总英雄经验=10*（1+（防守方用户等级-1）*0.2）

		1.2用户金币
		用户金币获得规则
		胜利
		同 接受悬赏获得金币的规则
		失败
		用户金币=8*（1+防守方用户等级*0.2)
		*/
		if($ret["ret"]["win"])
		{
			$hxp = 100 * (1 + ($tulv - 1) * 0.2);
			$gb = 0;
		}
		else
		{
			$hxp = 10 * (1 + ($tulv - 1) * 0.2);
			$gb = 8 * (1 + $tulv * 0.2);
		}
	}

	public static function testfight($uid = 0, $tuid = 0)
	{
		$uid = intval($uid);
		$tuid = intval($tuid);
		if(!$uid || !$tuid) return array('ecode' => ERR302);

		$ret = self::fight($uid, $tuid);
		if($ret["ecode"]) return $ret;
		else
		{
			$ret["ret"]["reward"]["user"] = array("gb" => 0, "price" => 0);
			$ret["ret"]["reward"]["hero"] = array(1 => 0, 2 => 0);
			$ret["ret"]["reward"]["stuff"] = array("y1" => 0);
			$ret["ret"]["reward"]["equip"] = array("w1" => 1);
		}
		return $ret;
	}

	public static function fight($uid = 0, $tuid = 0)
	{
		$uid = intval($uid);
		$tuid = intval($tuid);
		if(!$uid || !$tuid) return array('ecode' => ERR302);

		$uext = daocall("user", "getuserext", array($uid));
        if (!$uext || !is_array($uext)) return array('ecode' => ERR402);
		$uext["lv"] = modcall("user", "xp2lv", array($uext["xp"]));
		$ulv = $uext["lv"]; 

		$tuext = daocall("user", "getuserext", array($tuid));
        if (!$tuext || !is_array($tuext)) return array('ecode' => ERR402);
		$tuext["lv"] = modcall("user", "xp2lv", array($tuext["xp"]));
		$tulv = $tuext["lv"];

		$hgs = daocall("herogroup", "getherogroups", array($uid));
		$thgs = daocall("herogroup", "getherogroups", array($tuid));
        if (!$hgs || !$thgs) return array('ecode' => ERR508);
		$cherogroup = $tcherogroup = array();
		foreach($hgs as $gid => $grow)
		{
			if($grow["stat"])
			{
				$cherogroup = $grow;
				break;
			}
		}
		foreach($thgs as $gid => $grow)
		{
			if($grow["stat"])
			{
				$tcherogroup = $grow;
				break;
			}
		}
		unset($hgs, $thgs);
		if(!$cherogroup || !$tcherogroup) return array('ecode' => ERR508);

		$heros = daocall("hero", "getheros", array($uid));
		$theros = daocall("hero", "getheros", array($tuid));
		if(!$heros || !$theros) return array('ecode' => ERR505);

		$equips = daocall("equip", "getequips", array($uid));
		$tequips = daocall("equip", "getequips", array($tuid));
        if ($equips === false || !is_array($equips) || $tequips === false || !is_array($tequips)) return array("ecode" => ERR601);

		$heroconfpre = &load_conf("pub:hero");
		if(!$heroconfpre || !$heroconfpre["hero"]) return array('ecode' => ERR505);
		$heroconf = $heroconfpre["hero"];

		//英雄穿装备
		foreach($equips as $eid => $erow)
		{
			if(!$erow["hid"]) continue;
			$heros[$erow["hid"]]["equip"][$eid] = $erow;
		}
		foreach($tequips as $eid => $erow)
		{
			if(!$erow["hid"]) continue;
			$theros[$erow["hid"]]["equip"][$eid] = $erow;
		}

		//装备英雄属性
		foreach($heros as $hid => $hrow)
		{
			self::equiphero(&$heros[$hid], $ulv);
		}
		foreach($theros as $hid => $hrow)
		{
			self::equiphero(&$theros[$hid], $tulv);
		}

		$attlog = array();
		$finished = false;
		while(!$finished)
		{
			$noatt = true;
			for($i = 1; $i < 10; $i ++)
			{
				switch($i)
				{
					case 1:
					case 4:
					case 7:
						$attorder = array(1, 4, 7, 2, 5, 8, 3, 6, 9);
						break;
					case 2:
					case 5:
					case 6:
						$attorder = array(2, 5, 8, 1, 4, 7, 3, 6, 9);
						break;
					case 3:
					case 6:
					case 9:
						$attorder = array(3, 6, 9, 1, 4, 7, 2, 5, 8);
						break;
				}

				$attside = $cherogroup["grid"][$i] ? "a" : ($tcherogroup["grid"][$i] ? "b" : "");//先进攻方
				if(!$attside) continue;

				$aside = $attside == "a" ? $cherogroup["grid"][$i] : 0;
				$bside = $attside == "b" ? $tcherogroup["grid"][$i] : 0;
				
				//找对手
				foreach($attorder as $pos2)
				{
					if($attside == "a" && $tcherogroup["grid"][$pos2])
					{
						$bside = $tcherogroup["grid"][$pos2];
						if($theros[$bside]["blood"]) break;
					}
					elseif($attside == "b" && $cherogroup["grid"][$pos2])
					{
						$aside = $cherogroup["grid"][$pos2];
						if($heros[$aside]["blood"]) break;
					}
				}

				if(!$aside || !$bside) continue;
				if(!$heros[$aside]["blood"] || !$theros[$bside]["blood"]) continue;

				self::attack(&$heros, &$theros, $aside, $bside, $uext, $tuext, &$attlog);//正方进攻
				if($heros[$aside]["blood"] && $theros[$bside]["blood"])
				{
					self::attack(&$theros, &$heros, $bside, $aside, $tuext, $uext, &$attlog);//反方进攻
				}
				$noatt = false;
			}
			if($noatt) $finished = true;
		}

		$win = 0;
		foreach($cherogroup["grid"] as $hid)
		{
			if($heros[$hid]["blood"])
			{
				$win = 1;
				$atkrow = daocall("fight", "getuseratk", array($uid, $tuid));
				if($atkrow) daocall("fight", "setuseratk", array($uid, $tuid, array("tm" => time())));
				else daocall("fight", "newuseratk", array($uid, $tuid, array("tm" => time())));
				break;
			}
		}

		return array("ecode" => SUCCESS, "ret" => array("win" => $win, "log" => $attlog));
	}

	public static function getsuccluck($uid = 0, $tuid = 0)
	{
		$uid = intval($uid);
		$tuid = intval($tuid);
		if(!$uid || !$tuid) return array('ecode' => ERR302);

		$uext = daocall("user", "getuserext", array($uid));
        if (!$uext || !is_array($uext)) return array('ecode' => ERR402);
		$uext["lv"] = modcall("user", "xp2lv", array($uext["xp"]));
		$ulv = $uext["lv"]; 

		$atkrow = daocall("fight", "getuseratk", array($uid, $tuid));
		if(!$atkrow || $atkrow["tm"] < mktime(0, 0, 0, date("m"), date("d"), date("Y"))) return array('ecode' => ERR701);

		$confpre = load_conf("pub:atkluck");
		if(!$confpre || !$confpre["atkluck"]) return false;
		$conf = $confpre["atkluck"];

		$rateall = 0;
		$prerate = 0;
		foreach($conf as $sid => $srow) $rateall += $srow["rate"];
		$rateall = round($rateall * 100);
		foreach($conf as $sid => $srow)
		{
			$crate = round(($srow["rate"] / $rateall) * 100);
			$conf[$sid]["realrate"] = array($prerate, $prerate + $crate);
			$prerate += $crate;
		}

		$lucks = array();
		for($i = 0; $i < 5; $i ++)
		{
			$rnd = rand(1, $rateall);
			foreach($conf as $sid => $srow)
			{
				if($rnd > $srow["realrate"][0] && $rnd <= $srow["realrate"][1])
				{
					if(in_array($sid, $lucks))
					{
						$i --;
						break;
					}
					$lucks[] = $sid;
					break;
				}
			}
		}

		if(!daocall("fight", "setuseratk", array($uid, $tuid, array("lucks" => $lucks)))) return array('ecode' => ERR702);

		return array("ecode" => SUCCESS, "ret" => $lucks);
	}

	public static function succluck($uid = 0, $tuid = 0, $drops = array())
	{
		$uid = intval($uid);
		$tuid = intval($tuid);
		if(!$uid || !$tuid) return array('ecode' => ERR302);

		$uext = daocall("user", "getuserext", array($uid));
        if (!$uext || !is_array($uext)) return array('ecode' => ERR402);
		$uext["lv"] = modcall("user", "xp2lv", array($uext["xp"]));
		$ulv = $uext["lv"]; 

		$atkrow = daocall("fight", "getuseratk", array($uid, $tuid));
		if(!$atkrow || $atkrow["tm"] < mktime(0, 0, 0, date("m"), date("d"), date("Y")) || !$atkrow["lucks"]) return array('ecode' => ERR701);

		$usets = array();
		if($drops)
		{
			if($uext["mb"] < count($drops) * 2) return array('ecode' => ERR403);

			$uext["mb"] -= count($drops) * 2;
			$usets["mb"] = $uext["mb"];

			foreach($drops as $idx)
			{
				if($atkrow["lucks"][$idx]) unset($atkrow["lucks"][$idx]);
			}
		}

		$rnd = rand(1, 100);
		$unitrate = 100 / count($atkrow["lucks"]);
		$nowrate = 0;
		$luck = "";
		foreach($atkrow["lucks"] as $luckv)
		{
			if($rnd > $nowrate && $rnd <= $nowrate + $unitrate)
			{
				$luck = $luckv;
				break;
			}
			$nowrate += $unitrate;
		}

		$confpre = load_conf("pub:stuff");
		if(!$confpre || !$confpre["stuff"]) return false;
		$conf = $confpre["stuff"];
		$rid = 0;
		if($conf[$luck])
		{
			$stuff = &daocall("stuff", "getstuffs", array($uid));
			if(!daocall("stuff", "setstuff", array($uid, $luck, intval($stuff[$luck]["cnt"]) + $cnt))) return array('ecode' => ERR602);
		}
		else
		{
			$confpre = load_conf("pub:equip");
			if(!$confpre || !$confpre["equip"]) return false;
			$conf = $confpre["equip"];
			if(!$conf[$luck]) return array('ecode' => ERR603);

			$rid = daocall("equip", "newequip", array($uid, array("etype" => $luck)));
			if(!$rid) return array('ecode' => ERR604);
		}

		if($usets && !daocall("user", "setuserext", array($uid, $usets))) return array('ecode' => ERR407);

		return array("ecode" => SUCCESS, "ret" => array("sn" => $luck, "id" => $rid));
	}

	//装备属性
	private static function equiphero(&$hero, $ulv = 0)
	{
		$confpre = load_conf("pub:hero");
		
		if(!$confpre || !$confpre["hero"] || !$confpre["hero"][$hero["hsn"]]) return false;
		$conf = $confpre["hero"][$hero["hsn"]];

		/*
		主属性基本值：
		力量：初始力量+（等级-1）*成长力量
		敏捷：初始敏捷+（等级-1）*成长敏捷
		智力：初始智力+（等级-1）*成长智力
		*/
		$mainprop = $conf["type"] == 3 ? ($conf["iwit"] + ($ulv - 1) * $conf["gwit"]) 
			: ($conf["type"] == 2 ? ($conf["irate"] + ($ulv - 1) * $conf["grate"]) 
			: ($conf["iforce"] + ($ulv - 1) * $conf["gforce"]));
		$hero["minatt"] = $conf["dice"] + $conf["ihurt"] + $mainprop;//最小攻击：骰子+基本攻击+主属性基本值
		$hero["maxatt"] = $conf["dice"] * $conf["bias"] + $conf["ihurt"] + $mainprop;//最大攻击：主属性基本值+骰子*偏斜+基本攻击
		$hero["protect"] = $conf["iprotect"] - 1 + ($conf["irate"] + ($ulv - 1) * $conf["grate"])/7;//护甲：基础防御-1+基础敏捷/7
		$hero["huff"] = $conf["bias"] * 0.005;//暴击：偏斜*0.005,暴击伤害为原伤害的150%
		$hero["away"] = $conf["bias"] * 0.003;//躲闪：偏斜*0.003,成功时不会受到任何伤害
		$hero["blood"] = $conf["ablood"] + 19 * ($conf["iforce"] + ($ulv - 1) * $conf["gforce"]);//生命值：附加生命+19*力量

		/*
		技能：
		物理伤害公式：【1-（护甲值*0.06）/（1+护甲值*0.06）】*初始伤害=实际伤害
		*/

		$confpre = load_conf("pub:equip");
		if($confpre && $confpre["equip"] && $hero["equip"])
		{
			$conf = $confpre["equip"];
			foreach($hero["equip"] as $eid => $erow)
			{
				if(!$conf[$erow["etype"]]) continue;
				$hurt = $conf[$erow["etype"]]["hurt"];
				if(is_array($hurt)) $hurt = rand($hurt[0], $hurt[1]);
				$blood = $conf[$erow["etype"]]["blood"];
				if(is_array($blood)) $blood = rand($blood[0], $blood[1]);
				$protect = $conf[$erow["etype"]]["protect"];
				if(is_array($protect)) $protect = rand($protect[0], $protect[1]);
				$escape = $conf[$erow["etype"]]["escape"];
				if(is_array($escape)) $escape = rand($escape[0], $escape[1]);

				if($hurt) $hero["exatt"] += $hurt;
				if($blood) $hero["exblood"] += $blood;
				if($protect) $hero["exprotect"] += $protect;
				if($escape) $hero["exaway"] += $escape;
			}
		}
	}

	//战斗
	private static function attack(&$heros, &$theros, $aside = 0, $bside = 0, $uext = array(), $tuext = array(), &$attlog)
	{
		$ulv = $uext["lv"];
		$tulv = $tuext["lv"];

		$s = $t = array();

		$s["a"]["heros"] = &$heros;
		$s["a"]["side"] = $aside;
		$s["a"]["u"] = &$uext;
		$s["a"]["hero"] = &$heros[$aside];

		$s["b"]["heros"] = &$theros;
		$s["b"]["side"] = $bside;
		$s["b"]["u"] = &$tuext;
		$s["b"]["hero"] = &$theros[$bside];
		
		//计算被攻击方的闪避
		if(rand(1, 100) <= round(($s["b"]["hero"]["away"] + $s["b"]["hero"]["exaway"]) * 100))
		{
			//闪避成功
			$attlog[] = array(
				"action" => 1, //闪避
				"uid" => $s["a"]["u"]["uid"], //出击方UID
				"tuid" => $s["b"]["u"]["uid"] //被攻方UID
				);
		}
		else
		{
			$ohurt = $hurt = rand($s["a"]["hero"]["minatt"], $s["a"]["hero"]["maxatt"]) + $s["a"]["hero"]["exatt"];//最终的攻击
			$huff = 0;
			if(rand(1, 100) <= round($s["a"]["hero"]["huff"] * 100))
			{
				$hurt *= 1.5;//暴击伤害为原伤害的150%
				$huff = 1;
			}
			$protect = $s["b"]["hero"]["protect"] + $s["b"]["hero"]["exprotect"];//最终的防御
			$hurt -= $protect;

			$s["b"]["hero"]["blood"] -= $hurt;//被攻击方的血量
			$s["b"]["hero"]["blood"] = $s["b"]["hero"]["blood"] > 0 ? $s["b"]["hero"]["blood"] : 0;

			$attlog[] = array(
				"action" => 2, //攻击
				"uid" => $s["a"]["u"]["uid"], //出击方UID
				"tuid" => $s["b"]["u"]["uid"], //被攻方UID
				"hid" => $s["a"]["hero"]["hid"], //被攻方英雄
				"thid" => $s["b"]["hero"]["hid"], //被攻方英雄
				"hurt" => round($ohurt, 2), //基础伤害
				"huff" => $huff, //是否暴击
				"protect" => round($protect, 2), //防御
				"hurtblood" => round($hurt, 2), //掉血
				"leftblood" => round($s["b"]["hero"]["blood"], 2) //剩余血量
				);
		}
	}

}
?>